
module keccakf(
    input clk,
    input rst,
    
    input [4:0] round,
    
    input                    r2s_we,
    input [1:0]              r2s_we_sel,
    input [31:0]             r2s_data,
    
    output [99:0] data_out,
    
    input always_round,
    input one_round
);
    reg [99:0] state;
    wire [99:0] lin_state;
    reg [2:0] rc;
    always@(*) begin 
        case(round)
            0: rc = 3'b001;
            1: rc = 3'b010;
            2: rc = 3'b110;
            3: rc = 3'b000;
            4: rc = 3'b111;
            5: rc = 3'b001;
            6: rc = 3'b001;
            7: rc = 3'b101;
            8: rc = 3'b110;
            9: rc = 3'b100;
            10:rc = 3'b101;
            11:rc = 3'b110;
            12:rc = 3'b111;
            13:rc = 3'b111;
            14:rc = 3'b101;
            15:rc = 3'b011;
            default: rc = 3'b001;
        endcase
    end
    
    initial begin
       state = 100'h810a7d646fc5b66ab73a405ba;
    end
    
    always@(posedge clk or negedge rst) begin 
        if (!rst) begin
            state <= 100'hfdb82f0c9f389f1a7810157fb;
        end
        else if (round == 0) begin 
            state <= state;
        end else begin
            if (always_round == 1'b1) begin
                state <= lin_state;
            end
            else begin
                if (one_round == 1'b1)begin
                    state <= lin_state;
                end
                else begin
                    if(r2s_we == 1'b1)begin
                        case(r2s_we_sel)
                          2'b00: state[3:0]   <= r2s_data[31:28];
                          2'b01: state[35:4]  <= r2s_data;
                          2'b10: state[67:36] <= r2s_data;
                          2'b11: state[99:68] <= r2s_data;
                        endcase
                    end else begin
                        state <= state;
                    end
                end
            end
        end 
    end 
    
    keccakf_round u_round(state,rc,lin_state);
    
    assign data_out = state;
endmodule
